////////////////////////////////////////////////////////////////////////////////
/// @file    play_wavfile.c
/// @author  AE TEAM
/// @brief   THIS FILE PROVIDES ALL THE SYSTEM FUNCTIONS.
////////////////////////////////////////////////////////////////////////////////
/// @attention
///
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
///
/// <H2><CENTER>&COPY; COPYRIGHT MINDMOTION </CENTER></H2>
////////////////////////////////////////////////////////////////////////////////
// Define to prevent recursive inclusion
#define _PLAY_WAVFILE_C_

// Files includes

//file play_wavfile.c
#include "HAL_conf.h"
#include "HAL_device.h"
#include <stdio.h>
#include <string.h>
#include "bsp_WM8978.h"

#include "play_wavfile.h"
#include "wav_operate.h"
#include "sdio.h"
#include "ff.h"
#include "fatfs.h"
#include "sdio_sdcard.h"

#include "uart.h"
#include "delay.h"
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup MM32_Example_Layer
/// @{

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup PLAY_WAVFILE
/// @{

////////////////////////////////////////////////////////////////////////////////
/// @addtogroup PLAY_WAVFILE_Exported_Constants
/// @{


#define FULLBUFFERBYTELEN  (512*10)
#define HALFBUFFERLEN  (FULLBUFFERBYTELEN/2)
#define FULLBUUFERHALFWORDLEN  (FULLBUFFERBYTELEN/2)
#define HALFBUUFERHALFWORDLEN  (FULLBUFFERBYTELEN/4)


//u16 I2sSendBuffer[1024];// 512 halfword , 1024 bytes;
u8  FileReadBuffer[FULLBUFFERBYTELEN];
u32 RealReadbackBytesNumber;

bool FileEndFlag = 0;
////////////////////////////////////////////////////////////////////////////////
/// @brief  Transfer files.
/// @param  None.
/// @retval  0.
////////////////////////////////////////////////////////////////////////////////
void FillDataMode1withwavfile(void)
{
    u32 waittoSendCounter = 0;
    readwavfile();
    while(1) {
        f_lseek(&fileR, WaveCounter);
        FileEndFlag = 0;
        if(WaveLen > FULLBUFFERBYTELEN) {
            f_read(&fileR, FileReadBuffer, FULLBUFFERBYTELEN, &RealReadbackBytesNumber);
            waittoSendCounter = WaveLen - FULLBUFFERBYTELEN;
            FileEndFlag = 0;
            I2S_TX_DMAPolling_Circular_Auto_Reload_Enable_Init((u16*)&FileReadBuffer[0], FULLBUFFERBYTELEN / 2);
            DMA_Cmd(DMA1_Channel3, ENABLE);
        }
        else {
            f_read(&fileR, FileReadBuffer, WaveLen, &RealReadbackBytesNumber);
            FileEndFlag = 1;
            I2S_TX_DMAPolling_Circular_Auto_Reload_Enable_Init((u16*)&FileReadBuffer[0], RealReadbackBytesNumber / 2);
            DMA_Cmd(DMA1_Channel3, ENABLE);
        }

        while(1) {
            if(FileEndFlag == 0) {
                if(DMA_GetITStatus(DMA1_IT_HT3) == SET) {
                    DMA_ClearITPendingBit(DMA1_IT_HT3);

                    if(waittoSendCounter > HALFBUFFERLEN) {
                        f_read(&fileR, FileReadBuffer, HALFBUFFERLEN, &RealReadbackBytesNumber);
                        waittoSendCounter = waittoSendCounter - HALFBUFFERLEN;
                        FileEndFlag = 0;
                    }
                    else {
                        f_read(&fileR, FileReadBuffer, waittoSendCounter, &RealReadbackBytesNumber);
                        if((HALFBUFFERLEN - waittoSendCounter) != 0) {
                            memset(FileReadBuffer + waittoSendCounter, 0, HALFBUFFERLEN + HALFBUFFERLEN - waittoSendCounter);
                        }
                        waittoSendCounter = 0;
                        FileEndFlag = 1;
                    }
                }
                else if(DMA_GetITStatus(DMA1_IT_TC3) == SET) {
                    DMA_ClearITPendingBit(DMA1_IT_TC3);

                    if(waittoSendCounter > HALFBUFFERLEN) {
                        f_read(&fileR, FileReadBuffer + HALFBUFFERLEN, HALFBUFFERLEN, &RealReadbackBytesNumber);
                        waittoSendCounter = waittoSendCounter - HALFBUFFERLEN;
                        FileEndFlag = 0;
                    }
                    else {
                        f_read(&fileR, FileReadBuffer + HALFBUFFERLEN, waittoSendCounter, &RealReadbackBytesNumber);
                        if((HALFBUFFERLEN - waittoSendCounter) != 0) {
                            memset(FileReadBuffer + HALFBUFFERLEN + waittoSendCounter, 0, HALFBUFFERLEN - waittoSendCounter);
                        }
                        waittoSendCounter = 0;
                        FileEndFlag = 1;
                    }
                }
            }
            else {
                if(DMA_GetITStatus(DMA1_IT_TC3) == SET) {
                    DMA_ClearITPendingBit(DMA1_IT_GL3);
                    DMA_ClearITPendingBit(DMA1_IT_TC3);
                    f_lseek(&fileR, WaveCounter);
                    waittoSendCounter = 0;
                    FileEndFlag = 0;
                    RealReadbackBytesNumber = 0;
                    f_lseek(&fileR, WaveCounter);
                    break;
                }

            }
        }

    }
}
////////////////////////////////////////////////////////////////////////////////
/// @brief  I2S initialize.
/// @param  None.
/// @retval  0.
////////////////////////////////////////////////////////////////////////////////
void initI2S_CodecMode1(void)
{
    DELAY_Init();
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBENR_SDIO, ENABLE);
    CONSOLE_Init(115200);

    wm8978_Init();

    I2S_CODEC_Init();

    StartPlay();

}
////////////////////////////////////////////////////////////////////////////////
/// @brief   The I2S data transfer function is called by the SPI2 (I2S) interrupt service routine.
/// @note    Both recording and playback are handled in this function.
/// @param   None
/// @retval  None
////////////////////////////////////////////////////////////////////////////////
void DMA1_Channel3_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_TC3) == SET) {
        DMA_ClearITPendingBit(DMA1_IT_TC3);

    }
}
////////////////////////////////////////////////////////////////////////////////
/// @brief  I2S with WM8978 and MM32 starts to play.
/// @param  None
/// @retval None
////////////////////////////////////////////////////////////////////////////////
void StartPlay(void)
{
    int i;

    i = 100000;
    while(i--);
    wm8978_Init();
    I2S_Stop();


    wm8978_Dac2Spk();


    wm8978_ChangeVolume(20, 20);


    wm8978_CfgAudioIF(I2S_Standard_Phillips, 16, SPI_Mode_Master);


    I2S_StartPlay((SPI_I2S_STANDARD_TypeDef)I2S_Standard_Phillips, (SPI_I2S_DATAFORMAT_TypeDef)I2S_DataFormat_16b, I2S_AudioFreq_48k);
}

////////////////////////////////////////////////////////////////////////////////
/// @brief  play music.
/// @param  None.
/// @retval None.
////////////////////////////////////////////////////////////////////////////////
void PlayWaveFileDmaPollingDemo(void)
{
    initI2S_CodecMode1();
    while(1) {
        FillDataMode1withwavfile();
    }
}

/// @}

/// @}

/// @}

